package com.hmall.order.util;

public class SnowflakeIdGenerator {
    
    private final long epoch = 1609430400000L; // 设置起始时间(2021-01-01)
    
    private final long machineIdBits = 10L;
    private final long maxMachineId = -1L ^ (-1L << machineIdBits);
    
    private final long sequenceBits = 12L;
    private final long machineIdShift = sequenceBits;
    
    private final long timestampShift = sequenceBits + machineIdBits;
    
    private long lastTimestamp = -1L;
    private long sequence = 0L;
    private long machineId;
    
    public SnowflakeIdGenerator(long machineId) {
        if (machineId < 0 || machineId > maxMachineId) {
            throw new IllegalArgumentException("Machine Id can't be greater than " + maxMachineId + " or less than 0");
        }
        this.machineId = machineId;
    }
    
    public synchronized long generateId() {
        long currentTimestamp = System.currentTimeMillis();
        
        if (currentTimestamp < lastTimestamp) {
            throw new RuntimeException("Invalid System Clock!");
        }
        
        if (currentTimestamp == lastTimestamp) {
            sequence = (sequence + 1) & ((1 << sequenceBits) - 1);
            if (sequence == 0) {
                currentTimestamp = getNextTimestamp();
            }
        } else {
            sequence = 0L;
        }
        
        lastTimestamp = currentTimestamp;
        
        return ((currentTimestamp - epoch) << timestampShift) | (machineId << machineIdShift) | sequence;
    }
    
    private long getNextTimestamp() {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }
}
